package com.smedi.ismedi.web.starter.config;

import com.smedi.ismedi.web.starter.async.ContextAwarePoolExecutor;
import com.smedi.ismedi.web.starter.common.AsyncContextCopyData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

@Slf4j
@Configuration
public class AsyncThreadPoolConfig {
    @Value("${spring.application.name}")
    private String threadNamePrefix;    // 线程池名前缀

    private static final int cpu = Runtime.getRuntime().availableProcessors();// 获取当前机器CPU数量

    private static final int corePoolSize = cpu;            // 核心线程数（默认线程数）

    private static final int maxPoolSize = cpu * 2;            // 最大线程数

    private static final int keepAliveTime = 60;            // 允许线程空闲时间（单位：默认为秒）

    private static final int queueCapacity = 200;            // 缓冲队列数

    public static final String asyncThreadName = "ismediAsyncThread";

    @Bean(asyncThreadName)
    public Executor taskExecutor() {
        log.info("配置异步线程池");

        ContextAwarePoolExecutor executor = new ContextAwarePoolExecutor();
        executor.setTaskDecorator(new AsyncContextCopyData()); // 上下文内容
        executor.setCorePoolSize(corePoolSize); // 核心线程数目
        executor.setMaxPoolSize(maxPoolSize);   // 指定最大线程数
        executor.setQueueCapacity(queueCapacity);   // 队列中最大的数目
        executor.setKeepAliveSeconds(keepAliveTime);    // 线程空闲后的最大存活时间
        executor.setThreadNamePrefix(threadNamePrefix + "-"); // 前缀
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());  // 线程池对拒绝任务的处理策略
        executor.setWaitForTasksToCompleteOnShutdown(true); // 线程池关闭的时候等待所有任务都完成再继续销毁其他的Bean
        executor.setAwaitTerminationSeconds(60); // 设置线程池中任务的等待时间，如果超过这个时候还没有销毁就强制销毁，以确保应用最后能够被关闭，而不是阻塞住。

        // 初始化
        executor.initialize();
        return executor;
    }



}
